package com.tinfeng.oop;

public class SubCat extends SuperJavaExtends {
    public void sleep() {
        System.out.println(this.getName() + "睡大觉zzz");
    }
    public void run() {
        System.out.println("猫猫跑步");
    }

    public static void main(String[] args) {
        SubCat subCat = new SubCat();
        subCat.setName("狗");
        subCat.sleep();
        subCat.eat();
        subCat.run();
        SuperJavaExtends cat = new SubCat();
        if (cat instanceof SubCat) {
            SubCat subCat1 = (SubCat) cat;
            System.out.println("yes");
        }
        // 向下转型，因为SuperJavaExtends对象的cat 无法调用自带的方法  子类引用指向父类实例
        SubCat cat1 = (SubCat) cat;
        cat1.run();

    }

    @Override
    public void eat() {
            // 重写加 this
        System.out.println(this.getName()+"在吃屎");
        /** 重写规则:
         * 重写方法的参数列表应该与原方法完全相同；
         * 返回值类型应该和原方法的返回值类型一样或者是它在父类定义时的子类型；
         * 重写方法访问级别限制不能比原方法高。例如：如果父类方法声明为公有的，那么子类中的重写方法不能是私有的或是保护的。具体限制级别参考访问修饰符；
         * 只有被子类继承时，方法才能被重写；
         * 方法定义为 final，将不能被重写（final 关键字将在本节后面讲到）；
         * 一个方法被定义为 static，将使其不能被重写，但是可以重新声明；
         * 一个方法不能被继承，那么也不能被重写；
         * 和父类在一个包中的子类能够重写任何没有被声明为 private 和 final 的父类方法；
         * 和父类不在同一个包中的子类只能重写 non-final 方法或被声明为 public 或 protected 的方法；
         * 一个重写方法能够抛出任何运行时异常，不管被重写方法是否抛出异常。然而重写方法不应该抛出比被重写方法声明的更新更广泛的已检查异常。重写方法能够抛出比被重写方法更窄或更少的异常；
         * 构造方法不能重写。
         */
        /**方法重写和方法重载的区别:
        Java 中的方法重写（Overriding）是说子类重新定义了父类的方法。方法重写必须有相同的方法名，参数列表和返回类型。覆盖者访问修饰符的限定大于等于父类方法。

        而方法重载（Overloading）发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况
        */

        /**
         * 访问修饰符：
         * public 公开的，可以在任何地方访问
         * private 私有的，只允许在本类中访问
         * protected  受保护的，允许在同一个类、同一个包以及不同包的子类中访问;
         * default(默认的)  允许在同一个类，同一个包中访问
         */

        /**
         * super 关键字
         * super 是用在子类中的，目的是访问直接父类的变量或方法。注意：
         *
         * super 关键字只能调用父类的 public 以及 protected 成员；
         * super 关键字可以用在子类构造方法中调用父类构造方法；
         * super 关键字不能用于静态 (static) 方法中。
         */
        // 调用父类构造方法 例子在subdog
        // 调用父类属性
        /**
         * class Pet {
         *   	protected String birthday;
         * }
         *
         * class Dog extends Pet {
         *   	public Dog() {
         *   	    System.out.println("宠物生日：" + super.birthday);
         *     }
         * }
         */
        // 调用父类方法
        /**
         * class Pet {
         *   	public void eat() {
         *       	System.out.println("宠物吃东西");
         *     }
         * }
         *
         * class Cat extends Pet{
         *   	public void eat() {
         *       	// 在 eat 方法中调用父类 eat 方法
         *       	super.eat();
         *       	System.out.println("小猫饭量很小");
         *     }
         * }
         *
         * class Test {
         *   	public static void main(String[] args) {
         *       	Cat cat = new Cat();
         *       	cat.eat();
         *     }
         * }
         */

        /**
         * super 与 this 的对比
         * this 关键字指向当前类对象的引用，它的使用场景为：
         *
         * 访问当前类的成员属性和成员方法；
         * 访问当前类的构造方法；
         * 不能在静态方法中使用。
         *
         * super 关键字指向父类对象的引用，它的使用场景为：
         *
         * 访问父类的成员属性和成员方法；
         * 访问父类的构造方法；
         * 不能在静态方法中使用。
         *
         * 另外，需要注意的是，在构造方法调用时，super 和 this 关键字不能同时出现。
         */

        // final 关键字
        // final 关键字可以作用于类、方法或变量，分别具有不同的含义。
        // 在使用时，必须将其放在变量类型或者方法返回之前，建议将其放在访问修饰符和 static 关键字之后
        // 定义一个常量
        //public static final int MAX_NUM =22;

        /**
         * final 作用于类
         *  final class test (){
         *      public String name;
         *  }
         *  但加了 final 后这个类不能被继承   继承便会报错 规定
         */

        /**
         * final 作用于方法
         * 当父类中的方法 不希望被重写则可以加 final
         * class SuperClass {
         *   	public final void finalMethod() {
         *     		System.out.println("我是final方法");
         *     }
         * }
         *
         * class SubClass extneds SuperClass {
         *   	// 被父类标记为final的方法不允许被继承，编译会报错
         *        @Override
         *    public void finalMethod() {
         *     }
         * }
         */

        /**
         * final 作用于变量
         * 实例变量，可以使用 final 修饰，其修饰的变量在初始化后就不能修改
         * class Cat {
         *   	public final String name = "小花";
         * }
         */
    }
}
